/**
 * 
 */
package com.servicecloud.filter;

import java.nio.charset.Charset;
import java.util.Base64;

import javax.servlet.http.HttpServletRequest;

import org.eclipse.jetty.http.HttpStatus;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.util.StringUtils;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

/**
 * @Description 路由进行授权访问处理
 *              note:该过滤设置的安全认证信息是为了该路由网关能够访问服务而填写的账号密码，需要和服务里面设置的安全认证信息保持一致<br>
 *              consumer端访问zuul网关填写的账号密码是zuul设置的安全认证信息，在yml配置文件中<br>
 *              前置过滤器适合限流，校验参数的操作，如果有多个前置过滤器，那么限流应该放在最前面<br>
 *              常用的限流方式就是利用令牌桶的方式<br>
 * @author Gavin<br>
 *         2019年8月16日
 */
public class AuthorizedRequestFilter extends ZuulFilter {
	// 在进行Zuul过滤的时候可以设置其它过滤执行的位置，那么此时有如下几种类型：
	@Override
	public String filterType() {
		// 1. pre:在请求发出之前执行过滤，如果要进行访问，肯定在请求前设置头信息
		// 2. route: 在进行路由请求的时候被调用；
		// 3. post: 在路由之后发送请求信息的时候被调用；
		// 4. erro: 出现错误之后进行调用
		return FilterConstants.PRE_TYPE;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.netflix.zuul.ZuulFilter#filterOrder()
	 */
	@Override
	public int filterOrder() {// 设置优先级，数字越大优先级越低
		// 放到PreDecorationFilter过滤器之前
		return FilterConstants.PRE_DECORATION_FILTER_ORDER-1;
	}

	@Override
	public boolean shouldFilter() {// 表示当前filter是否执行，就是说是否对请求进行拦截
		// TODO Auto-generated method stub
		return true;
	}

	/*
	 * 表示具体的过滤执行操作
	 */
	@Override
	public Object run() {
		RequestContext requestContext = RequestContext.getCurrentContext();// 获取上下文内容
		HttpServletRequest request=requestContext.getRequest();//获取到request对象，然后可以对request里面的参数进行校验
		String auth = "springcloudzuul:service";// springsecurity设置的账号密码
		byte[] encodeAuth = Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));// 需要进行Base64加密
		String authHeader = "Basic " + new String(encodeAuth);// 需要注意Basic后面有一个空格
		requestContext.addZuulRequestHeader("Authorization", authHeader);
		
		//如果需要返回错误信息，比如校验token
		/*String token=request.getParameter("token");
		if(StringUtils.isEmpty(token)) {//自己的逻辑就是获取后和redis里面或者数据库里面的值进行比较
			requestContext.setSendZuulResponse(false);
			requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED_401.value());
		}
		*/
		/*
		 * 实现权限访问的拦截，比如只能买家访问，或者只能卖家访问，或者只能登录后才能访问服务。生产环境中一般不写到一起，因为写到一起耦合度太大，一般把每一个拦截的规则重新
		 * 写一个拦截器，然在shouldFilter里面写一个规则拦截一个，便于解耦。还有权限校验最好不要通过访问数据库和调用用户的服务来进行校验，最好通过读取redis的值来进行
		 * 校验用户信息
		 * */
		String url=request.getRequestURI();//获取到访问路径
		System.err.println(url);
		if(!"/Gavin/mydept/dept/list".equals(url)) { //如果访问的不是这个服务
			requestContext.setSendZuulResponse(false);
			requestContext.setResponseStatusCode(401);
		}
		return null;
	}
}
